﻿/****************************************************************
  Author:  Ievgenii Nazaruk, ievgenii.nazaruk@gmail.com 
 License:  Microsoft Public License (Ms-PL)
          ( http://www.opensource.org/licenses/ms-pl.html or
            http://www.microsoft.com/opensource/licenses.mspx )
*****************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Documents;
using TableParsers;
using System.Windows.Input;
using Frontend;
using System.Diagnostics;

using SpeakupBackend;
using SpeakupBackend.Classes;
using System.ComponentModel;

namespace Frontend
{
    class ClassPanel: ContentControl
    {
        public static Dictionary<ClassType, string> ClassTypeTitles;
        public static Dictionary<ClassType, string> ShortClassTypeTitles;

        public static Size SmallSize = new Size(35, 35);
        public static bool UseSmallSizeDetection = true;

        static readonly Brush ActiveTitleBrush = Brushes.Black;
        static readonly Brush InactiveTitleBrush = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0));
        static readonly Brush InactiveBackgroundBrush = new SolidColorBrush(Color.FromRgb(220, 220, 220));

        static ClassPanel()
        {
            ClassTypeTitles = new Dictionary<ClassType, string>();
            ClassTypeTitles[ClassType.Club] = "Club";
            ClassTypeTitles[ClassType.Business] = "Business English";
            ClassTypeTitles[ClassType.Group] = "Group Class";            
            ClassTypeTitles[ClassType.FirstClass] = "First Class";
            ClassTypeTitles[ClassType.ProgressFollowup] = "Progress Follow-up";
            ClassTypeTitles[ClassType.Grammar] = "Grammar";
            ClassTypeTitles[ClassType.Reading] = "Reading";
            ClassTypeTitles[ClassType.Writing] = "Writing";
            ClassTypeTitles[ClassType.Conversation] = "Conversation";

            ShortClassTypeTitles = new Dictionary<ClassType, string>();
            ShortClassTypeTitles[ClassType.Club] = "CC";
            ShortClassTypeTitles[ClassType.Business] = "BW";
            ShortClassTypeTitles[ClassType.Group] = "GC";
            ShortClassTypeTitles[ClassType.FirstClass] = "FC";
            ShortClassTypeTitles[ClassType.ProgressFollowup] = "PF";
            ShortClassTypeTitles[ClassType.Grammar] = "Gr";
            ShortClassTypeTitles[ClassType.Reading] = "Rd";
            ShortClassTypeTitles[ClassType.Writing] = "Wr";
            ShortClassTypeTitles[ClassType.Conversation] = "Con";
        }

        static private String GetClassTitle(Class speakupClass)
        {
            if(ClassTypeTitles.Keys.Contains(speakupClass.Name.Type))
            {
                return ClassTypeTitles[speakupClass.Name.Type];
            }

            return speakupClass.Name.ToString();
        }

        static private String GetShortClassTitle(Class speakupClass)
        {
            if (ShortClassTypeTitles.Keys.Contains(speakupClass.Name.Type))
            {
                return ShortClassTypeTitles[speakupClass.Name.Type];
            }
            return speakupClass.Name.ToString();
        }


        public Class SpeakupClass { get; private set; }

        private DockPanel Panel;
        private Border Border;
        private TextBlock Title;
        
        public ClassPanel(Class speakupClass)
        {
            SpeakupClass = speakupClass;

            {
                var proxy = new DelegateProxy<PropertyChangedEventHandler>();
                SpeakupClass.PropertyChanged += proxy.ProxyConsumer;
                proxy.ProxySource += (s,e) => UpdateUIState();
                proxy.ProxySource += (s,e) => UpdateZIndex();
            }
            
            m_original_zIndex = DockPanel.GetZIndex(this);

            //attaching time slot info to our control so we can correctly be displayed in time sheet
            TimeSlot timeSlot = new TimeSlot(speakupClass.Time.Begin, speakupClass.Time.End);
            this.SetValue(TimeSheet.TimeSlotProperty, timeSlot);
            this.SetValue(TimeSheet.DaySlotProperty, speakupClass.Time.Date);

            //create all ui elements, initialize ui state
            SetupUI();
            UpdateZIndex();
            UpdateUIState();
        }
        public void SetupUI()
        {
            VerticalAlignment = VerticalAlignment.Stretch;
            HorizontalAlignment = HorizontalAlignment.Stretch;

            /* border */
            Border = new Border();
            Border.BorderBrush = Brushes.Black.Clone();
            Border.BorderThickness = new Thickness(0.5);

            Content = Border;
            
            /* panel */
            DockPanel RawPanel = new DockPanel();
            RawPanel.Background = Brushes.White;
            Border.Child = RawPanel;

            Panel = new DockPanel();
            Panel.VerticalAlignment = VerticalAlignment.Stretch;
            RawPanel.Children.Add(Panel);
            
            /* title */
            Title = new TextBlock();
            Title.TextWrapping = TextWrapping.Wrap;
            Title.VerticalAlignment = VerticalAlignment.Center;
            Title.HorizontalAlignment = HorizontalAlignment.Center;
            Title.TextAlignment = TextAlignment.Center;

            Panel.Children.Add(Title);
        }

        public new bool IsEnabled
        {
            get
            {
                return base.IsEnabled;
            }
            set
            {
                base.IsEnabled = value;
                UpdateUIState();
            }
        }

        private bool m_activated = true;
        public bool IsActive
        {
            get
            {
                return m_activated;
            }
            set
            {
                if (m_activated != value)
                {
                    m_activated = value;

                    UpdateUIState();
                    OnActivationChanged();
                }
            }
        }

        private int m_original_zIndex = 0;
        private bool m_highlighted = false;
        public bool IsHighlighted
        {
            get
            {
                return m_highlighted;
            }
            set
            {
                if (m_highlighted != value)
                {
                    UpdateZIndex();
                    m_highlighted = value;

                    UpdateUIState();
                    OnHighlightChanged();
                }
            }
        }

        private bool m_selected = false;
        public bool IsSelected
        {
            get
            {
                return m_selected;
            }
            set
            {
                if (value != m_selected)
                {
                    m_selected = value;

                    UpdateUIState();
                    OnSelectionChanged();
                }
            }
        }

        private bool m_useShortTitle = false;
        private bool UseShortTitle
        {
            get
            {
                return m_useShortTitle;
            }
            set
            {
                if (value != m_useShortTitle)
                {
                    m_useShortTitle = value;
                    UpdateUIState();
                }
            }
        }

        void UpdateUIState()
        {
            //panel is disabled
            if (!IsEnabled)
            {
                UpdateSelectedUIState(false);
                UpdateHighlightUIState(false);
                UpdateActivationUIState(false);                
            }
            //panel is enabled
            else
            {
                UpdateActivationUIState(IsActive);

                if (IsActive)
                {
                    //panel can be highlighted only when it is active
                    UpdateHighlightUIState(IsHighlighted);
                }

                //panel can be selected even when it is deactivated
                UpdateSelectedUIState(IsSelected);
            }

            UpdateTitleUIState();
        }

        void UpdateZIndex()
        {
            if (!IsHighlighted)
            {
                if (SpeakupClass.DesiredStatus == ClassStatus.Reserved ||
                    SpeakupClass.DesiredStatus == ClassStatus.ReservedWaitList)
                {
                    DockPanel.SetZIndex(this, m_original_zIndex + 1);
                }
            }
            else
            {
                DockPanel.SetZIndex(this, m_original_zIndex + 10);
            }
        }

        public void DetectTitleMode()
        {
            bool shortTitle = false;

            if (UseSmallSizeDetection == false || RenderSize.IsEmpty)
            {
                shortTitle = false;
            }
            else
            {
                if (RenderSize.Height > SmallSize.Height &&
                    RenderSize.Width > SmallSize.Width)
                {
                    shortTitle = false;
                }
                else
                {
                    shortTitle = true;

                }
            }

            UseShortTitle = shortTitle;
        }

        void UpdateActivationUIState(bool activate)
        {
            if (activate)
            {
                Panel.Background = App.GetClassBrush(SpeakupClass.DesiredStatus);
                Title.Foreground = ActiveTitleBrush;
            }
            else
            {
                Panel.Background = InactiveBackgroundBrush;
                Title.Foreground = InactiveTitleBrush;
            }
        }

        void UpdateHighlightUIState(bool highlight)
        {
            if (highlight)
            {
                Panel.Background = App.GetHighlightedClassBrush(SpeakupClass.DesiredStatus);
            }
            else
            {
                Panel.Background = App.GetClassBrush(SpeakupClass.DesiredStatus);
            }
        }

        void UpdateSelectedUIState(bool select)
        {
            if(select)
            {
                Border.BorderBrush = Brushes.Red;
                Border.BorderThickness = new Thickness(2);
            }
            else
            {                
                Border.BorderBrush = Brushes.Black;
                Border.BorderThickness = new Thickness(0.5);                
            }
        }

        public void UpdateTitleUIState()
        {
            string title;
            if (UseShortTitle)
            {
                title = GetShortClassTitle(SpeakupClass);
            }
            else
            {
                title = GetClassTitle(SpeakupClass);
                if (SpeakupClass.Name.Kind == ClassKind.Club)
                {
                    title += "\n" + SpeakupClass.Name.Name;
                }
                else if (SpeakupClass.Name.Kind == ClassKind.Group)
                {
                    title += "\n" + SpeakupClass.Name.Name;
                }
            }

            Title.Inlines.Clear();

            Span sp = new Span(new Run(title));

            if (SpeakupClass.IsActionPending)
            {
                sp = new Bold(new Underline(new Run(title)));
            }

            Title.Inlines.Add(sp);
        }

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);
            DetectTitleMode();
        }

        protected override void OnMouseEnter(MouseEventArgs e)
        {
            base.OnMouseEnter(e);

            IsHighlighted = true;            
        }

        protected override void OnMouseLeave(MouseEventArgs e)
        {
            base.OnMouseLeave(e);

            IsHighlighted = false;
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            IsSelected = !IsSelected;            
        }

        protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
        {
            base.OnMouseDoubleClick(e);

            if (SpeakupClass.IsReservable)
            {
                SpeakupClass.Reserve();
            }
            else if (SpeakupClass.IsCancellable)
            {
                SpeakupClass.CancelReservation();
            }                               
        }

        public event EventHandler<EventArgs> ActivationChanged;
        protected void OnActivationChanged()
        {
            if (ActivationChanged != null)
            {
                ActivationChanged(this, new EventArgs());
            }
        }

        public event EventHandler<EventArgs> HighlightChanged;
        protected void OnHighlightChanged()
        {
            if (HighlightChanged != null)
            {
                HighlightChanged(this, new EventArgs());
            }
        }


        public event EventHandler<EventArgs> SelectionChanged;
        protected void OnSelectionChanged()
        {
            if (SelectionChanged != null)
            {
                SelectionChanged(this, new EventArgs());
            }
        }        
    }
}
